package com.veetao.api.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.math.NumberUtils;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;


public final class DataUtils {

	private static ObjectMapper mapper = new ObjectMapper();
	
	public static String serializeToJson(Object obj) {
		try {
			return mapper.writeValueAsString(obj);
		} catch (JsonProcessingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}
	public static <T> T deserializeFromJson(String jsonStr, Class<T> clz) {
		try {
			return  mapper.readValue(jsonStr, clz);
		} catch (JsonProcessingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}
	
	public static byte[] serialize(Object object) {
		ObjectOutputStream oos = null;
		ByteArrayOutputStream baos = null;
		try {
			// 序列化
			baos = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(baos);
			oos.writeObject(object);
			byte[] bytes = baos.toByteArray();
			return bytes;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static Object unserialize(byte[] bytes) {
		ByteArrayInputStream bais = null;
		try {
			// 反序列化
			bais = new ByteArrayInputStream(bytes);
			ObjectInputStream ois = new ObjectInputStream(bais);
			return ois.readObject();
		} catch (Exception e) {

		}
		return null;
	}
	public static int getIntValue(Map<String,String> map, String key) {
		String value = map.get(key);
		if(value != null && NumberUtils.isDigits(value)) {
			try {
				return Integer.parseInt(value);
			} catch(Exception e) {
				return 0;
			}
		}
		
		return 0;
	}
	public static long getLongValue(Map<String,String> map, String key) {
		String value = map.get(key);
		if(value != null && NumberUtils.isDigits(value)) {
			return Long.parseLong(value);
		}
		
		return 0;
	}
	/**
	 * @param sign
	 * @param string
	 * @return
	 * @author guohongtao
	 */
	public static String encode(String oriStr, String charset) {
		try {
			return URLEncoder.encode(oriStr, charset).replaceAll("\\+", "%20");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
		
	}
	/**
	 * @param payResultData
	 * @return
	 * @author guohongtao
	 */
	public static Map<String, String> generateParamMapFromQueryString(
			String queryStr) {
		Map<String,String> result = new HashMap<String, String>();
		String[] params = queryStr.split("&");
		for(String param : params) {
			String[] kv = param.split("=");
			if(kv.length == 2) {
				result.put(kv[0], kv[1]);
			}
		}
		return result;
	}
	/**
	 * @param payResultData
	 * @param string
	 * @return
	 * @author guohongtao
	 */
	public static String decode(String oriStr, String charset) {
		try {
			return URLDecoder.decode(oriStr, charset);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return null;
	}
	public static String getStringValue(Map<String, Object> map,
			String key) {
		Object value = map.get(key);
		return value == null ? null : value.toString();
	}
	
	public static <T> Set<T> generateInitializedSet(T[] values) {
		Set<T> set = new HashSet<T>();
		for(T v : values) {
			set.add(v);
		}
		return set;
	}
	
	/**
	 *  将List<T> 转换为List
	 * @param jsonStr
	 * @param typeReference  new TypeReference<List<T>>() {};
	 * @return
	 */
	public static <T> List<T> deserializeFromListJson(String jsonStr, Class<T> clz) {
		try {
//		①	JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, Bean.class);  
//			如果是Map类型  mapper.getTypeFactory().constructParametricType(HashMap.class,String.class, Bean.class);  
//			List<Bean> lst =  (List<Bean>)mapper.readValue(jsonString, javaType);   
			// 第二种 直接传入TypeReference<List<T>> typeReference4
			JavaType collectionType = getCollectionType(ArrayList.class, List.class, clz);
			return  mapper.readValue(jsonStr, collectionType);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	
	/**
	 *  将List<T> 转换为List
	 * @param jsonStr
	 * @param typeReference  new TypeReference<List<T>>() {};
	 * @return
	 * @throws IOException 
	 * @throws JsonMappingException 
	 * @throws JsonParseException 
	 */
	public static <T> List<T> deserializeFromListJsonWithNotCatch(String jsonStr, Class<T> clz) throws JsonParseException, JsonMappingException, IOException {
//		①	JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, Bean.class);  
//			如果是Map类型  mapper.getTypeFactory().constructParametricType(HashMap.class,String.class, Bean.class);  
//			List<Bean> lst =  (List<Bean>)mapper.readValue(jsonString, javaType);   
			// 第二种 直接传入TypeReference<List<T>> typeReference4
			JavaType collectionType = getCollectionType(ArrayList.class, List.class, clz);
			return  mapper.readValue(jsonStr, collectionType);
	}
	/**
	 *  将List<T> 转换为List
	 * @param jsonStr
	 * @param typeReference  new TypeReference<List<T>>() {};
	 * @return
	 */
	public static <T> List<T> deserializeFromListJson(String jsonStr, TypeReference<List<T>> typeReference) {
		try {
//		①	JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, Bean.class);  
//			如果是Map类型  mapper.getTypeFactory().constructParametricType(HashMap.class,String.class, Bean.class);  
//			List<Bean> lst =  (List<Bean>)mapper.readValue(jsonString, javaType);   
			// 第二种 直接传入TypeReference<List<T>> typeReference4
			List<T> list = mapper.readValue(jsonStr, typeReference);
			return list;
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	
	public static JavaType getCollectionType(Class<?> collectionClass,Class<?> collectionClassFor,Class<?>... elementClasses) {   
		        return mapper.getTypeFactory().constructParametrizedType(collectionClass, collectionClassFor,elementClasses);   
   }
	public static String createToken(String name) {
		long t = System.currentTimeMillis();
		String token = DigestUtils.md5Hex(name + "@@" + t  + "em911&ApiFRa$v");
		return token.toUpperCase();
	}
}
